package sketch.instrumenter;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;

import randoop.util.Files;
import sketch.util.Globals;

public class Tracer {
	
	public static final String SEP = "@";
	
	public static final String START = "START: ";
	
	public static final String END = "END: ";
	
	public static final String OBSERVER = "OBSERVE: ";
	
	public static final String OBSERVEREXPR = "OBSERVEEXPR: ";
	
	public static final String VALUE = "VALUE: ";
	
	public static final String FAIL = " fail()";
	
	public static final String NO_EXCEPTION = "NO_EXCEPTION: ";
	
	public static final String EXCEPTION_TYPE = "EXCEPTION_TYPE: ";
	
	public static File saveFile = new File("./traceFile.txt");
	
	public static boolean on = true;
	
	public static void turnOff() {
		on = false;
	}
	
	public static void turnOn() {
		on = true;
	}
	
	public synchronized static void clearFile() {
		FileOutputStream erasor;
		try {
			erasor = new FileOutputStream(saveFile);
			erasor.write(new byte[0]);
			erasor.flush();
			erasor.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static StringBuilder sb = new StringBuilder();
	
	public synchronized static void startMethod(String methodSignature) {
		//System.out.println("start method: " + methodSignature);
		if(!on) return;
		sb.append(START + methodSignature);
		sb.append(Globals.lineSep);
	}
	
	public synchronized static void endMethod(String methodSignature) {
		if(!on) return;
		sb.append(END + methodSignature);
		sb.append(Globals.lineSep);
		//write to the file incrementally
		try {
			BufferedWriter writer= new BufferedWriter(new FileWriter(saveFile, true)); /*Note, it is appending!*/
			writer.write(sb.toString());
			writer.flush();
			writer.close();
		} catch (IOException e) {
			throw new RuntimeException("The file: " + saveFile + " could not be incrementally updated!");
		}
		sb.delete(0, sb.length() - 1);
	}
	
	public synchronized static void recordObservation(int lineNum, String exprStr) {
		if(!on) return;
		sb.append(OBSERVER + exprStr + SEP + lineNum);
		sb.append(Globals.lineSep);
	}
	
	public synchronized static void recordObservationExpr(int lineNum, String exprStr, String... exprStrs) {
		if(!on) return;
		sb.append(OBSERVEREXPR + exprStr + SEP + lineNum + ", ");
		for(String str : exprStrs) {
			sb.append(str);
		}
		sb.append(Globals.lineSep);
	}
	
	public synchronized static void recordValue(String value) {
		if(!on) return;
		//System.out.println(value + "   " + System.currentTimeMillis());
		sb.append(VALUE + value);
		sb.append(Globals.lineSep);
	}
	
	public synchronized static void recordException(int lineNum, Throwable e) {
		if(!on) return;
		//record the  position of a block, and the exception it throws
		sb.append(EXCEPTION_TYPE + SEP + lineNum);
		sb.append(Globals.lineSep);
		sb.append(VALUE + e.getClass().getName());
		sb.append(Globals.lineSep);
	}
	
	public synchronized static void recordFailPosition(int lineNum) {
		if(!on) return;
		sb.append(NO_EXCEPTION + SEP + lineNum);
		sb.append(Globals.lineSep);
		sb.append(VALUE + FAIL);
		sb.append(Globals.lineSep);
	}
}